import stream from "stream";
// import msgpack from '@msgpack/msgpack';
import * as msgpack from "@msgpack/msgpack";
import {
  JSONRPCClient,
  JSONRPCServer,
  JSONRPCServerAndClient,
  JSONRPCServerAndClientOptions,
} from "json-rpc-2.0";

export class JSONRPCStream extends JSONRPCServerAndClient {
  public readonly stream: stream.Duplex;

  constructor(stream: stream.Duplex, options?: JSONRPCServerAndClientOptions) {
    const server = new JSONRPCServer();
    const client = new JSONRPCClient(
      (message) =>
        new Promise((resolve, reject) => {
          const payload = msgpack.encode(message, { useBigInt64: true });
          this.stream.write(payload, (error) => {
            if (error) {
              reject(error);
            } else {
              resolve();
            }
          });
        })
    );
    super(server, client, options);
    this.stream = stream;
  }
  listen() {
    const handle = async (payload: Uint8Array) => {
      const message = msgpack.decode(payload, { useBigInt64: true });
      await this.receiveAndSend(message).catch((error) => this.stream.emit("error", error));
    };
    this.stream.on("data", handle);
    this.stream.once("close", () => this.stream.off("data", handle));
  }
}
